<?php

namespace ObserverPattern;

/**
 * 观察者模式的角色和职责
 * 1. 主题(被观察者)接口(Subject)：定义了观察者注册、移除和通知的接口，同时维护观察者列表。
 * 2. 观察者接口(Observer)：定义了响应主题更新的通知接口。
 * 3. 主题实例(ConcreteSubject)：实现主题接口，并在自己状态发生变化时，通知所有的观察者。
 * 4. 观察者实例(ObserverSubject)：实现观察者接口，接到主题的通知后做出相应的处理
 */

// 定义主题(被观察者)接口，包含新增、移除、通知观察者的方法。 所需要的观察者列表则在实现类中去维护。
interface User
{
    // 新增粉丝
    public function addFlower(Flower $flower): void;
    // 移除粉丝
    public function removeFlower(Flower $flower): void;
    // 通知粉丝
    public function noticeFlower(string $content): void;
}

// 定义观察者接口，包含一个update方法
interface Flower
{
    // 用于处理收到主题通知后的操作
    public function update(string $userName, string $content): void;
}

// 实现观察者接口
class ConcreteFlower implements  Flower
{
    private string $name;
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function update(string $userName, string $content): void
    {
        echo "{$this->name} 收到通知， 你关注的用户 @ $userName 发布了一条新动态： $content\n";
        // 实际情况可能是通过websocket或其他方式通知到用户
    }
}

// 实现主题接口
class ConcreteUser implements User
{
    private array $flowerList = [];
    private string $name;

    /**
     * @param string $name
     */
    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function addFlower(Flower $flower): void
    {
        $this->flowerList[] = $flower;
    }

    public function removeFlower(Flower $flower): void
    {
        unset($this->flowerList[array_search($flower, $this->flowerList)]);
    }

    public function noticeFlower(string $content): void
    {
        foreach ($this->flowerList as $flower) {
            $flower->update($this->name, $content);
        }
    }

    // 发布动态，随后通知所有的粉丝
    public function post(string $content): void
    {
        // 1. 发布动态
        echo "$this->name 发布了新动态： $content\n";
        // 2. 通知粉丝
        $this->noticeFlower($content);
    }
}

// 测试
// 主题(被观察者)
$user = new ConcreteUser("azhen");
// 观察者
$f1 = new ConcreteFlower('张三');
$f2 = new ConcreteFlower('李四');
$f3 = new ConcreteFlower('王五');
$user->addFlower($f1);
$user->addFlower($f2);
$user->addFlower($f3);
// 发布动态
$user->post("越努力越幸运");